package common;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;

import math.LeastAbsMethodIterMin;
import math.LeastSquareMethod;
import math.WLeastAbsMethodIterMin;
import math.WLeastSquareMethod;
import math.common.MathCommon;
import math.probability.ExpDistribution;
import math.probability.LNormalDistribution;
import math.probability.LaplasDistribution;
import math.probability.NormalDistribution;
import math.probability.ProbDistribution;
import math.probability.UniformDistribution;

public class ErrorsInVariablesTestMain {
	
	
	public void doWork() throws FileNotFoundException {
		ProbDistribution distX = new ExpDistribution(1.0);
//		ProbDistribution distX = new NormalDistribution(0.0,2.0);
//		ProbDistribution distX = new LaplasDistribution();
//		ProbDistribution distX = new LNormalDistribution(-Math.log(3.0)/2.0, Math.log(3.0));
		ProbDistribution distEps = new NormalDistribution(0.0,0.3);
//		ProbDistribution distEps = new LaplasDistribution(4.5, 0.0);
		int nSet[] = {1000, 2000};
		Double [] aSet = {0.0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5};

		Double b0 = 1.0;
		Double b1 = 4.0;

//		PrintWriter out = new PrintWriter(new FileOutputStream("LAM_test.csv", true));
		System.out.println("X,A,N,alpha,beta");
		
		StatTest test = new X2onLAMvsWLAM();

		for (int n : nSet) {
//		System.out.println("Calculating n = " + n);
		StructuralModel modelH0 = new StructuralModel(n, distX, new NormalDistribution(0.0,0.0), distEps, b0,b1);
		for (Double a : aSet) {
			Double s2Xi = a/(1-a);
			StructuralModel modelH1 = new StructuralModel(n, distX, new NormalDistribution(0.0,s2Xi), distEps, b0,b1);
			Double M = 1000.0;
			StatTestTester tester = new StatTestTester(M.intValue(), test, modelH0, modelH1);
			tester.testAlpha_Beta();
			System.out.println(distX.toString() + "," + a + "," + n + "," + tester.getAlpha() + "," + tester.getBeta());
//			PrintWriter out1 = new PrintWriter(new FileOutputStream("statCorr"+distX.toString()+"_"+s+"_"+n+".csv"));
//			out1.println("H0_"+n+",H1_"+n);
//			ArrayList<Double> statH0 = tester.getStatH0();
//			ArrayList<Double> statH1 = tester.getStatH1();
//			for (int i = 0; i < statH0.size(); i++) {
//				out1.println(statH0.get(i) + "," + statH1.get(i));
//			}
//			out1.flush();
//			out1.close();
//			
		}
		}
//		out.flush();
//		out.close();
//			
	}
	
	public void doWork1() throws FileNotFoundException {
//		ProbDistribution distX = new ExpDistribution(0.75);
		ProbDistribution distX = new UniformDistribution(1.0, 5.6);
		ProbDistribution distEps = new NormalDistribution(0.0,0.1);
//		ProbDistribution distEps = new LaplasDistribution(4.5, 0.0);
		Double b0 = 0.5;
		Double b1 = 1.0;
		double s2Ksi[] = {0.5d, 1d, 1.5d};
		PrintWriter out = new PrintWriter(new FileOutputStream("TestEstH1_2.csv", true));
		out.println("X,eps,b1,s2Ksi,mean(b),var(b)");
		StatTest test = new X2Test();
		StructuralModel modelH0 = new StructuralModel(50, distX, new NormalDistribution(0.0,0.0), distEps, b0,b1);
		for (double s : s2Ksi) {
			StructuralModel modelH1 = new StructuralModel(50, distX, new NormalDistribution(0.0,s), distEps, b0,b1);
			StatTestTester tester = new StatTestTester(500, test, modelH0, modelH1);
			tester.testEstVarH1();
			out.println(distX.toString() + "," + distEps.toString() + "," + b1 + "," + s + "," + 
					tester.getMeanDiff() + "," + tester.getVarDiff());
					
		}
		out.flush();
		out.close();
			
	}
	
	public void doWork2() throws FileNotFoundException {
		ProbDistribution distX = new ExpDistribution(0.75);
//		ProbDistribution distX = new UniformDistribution(1.0, 5.6);
		ProbDistribution distEps = new NormalDistribution(0.0,0.1);
//		ProbDistribution distEps = new LaplasDistribution(4.5, 0.0);
		Double b0 = 0.5;
		Double b1 = 1.0;
		double s2Ksi[] = {0.5d};
//		PrintWriter out = new PrintWriter(new FileOutputStream("TestEstH1.csv", true));
//		out.println("X,eps,b1,s2Ksi,mean(b-bw),var(b-bw)");
		StatTest test = new X2onLAM();
		StructuralModel modelH0 = new StructuralModel(50, distX, new NormalDistribution(0.0,0.0), distEps, b0,b1);
		for (double s : s2Ksi) {
			StructuralModel modelH1 = new StructuralModel(50, distX, new NormalDistribution(0.0,s), distEps, b0,b1);
			StatTestTester tester = new StatTestTester(500, test, modelH0, modelH1);
//			tester.testEstVarH1();
//			System.out.println(distX.toString() + "," + distEps.toString() + "," + b1 + "," + s + "," + 
//					tester.getMeanDiff() + "," + tester.getVarDiff());
			tester.testAlpha_Beta();	
			System.out.println(distX.toString() + "," + s + "," + tester.getAlpha() + "," + tester.getBeta());
			
		}
//		out.flush();
//		out.close();
			
	}
	
	public void RealTest () throws FileNotFoundException {
		String input = "cons.csv";
		Scanner scanner = new Scanner (new File(input));
		Map<Double, Double> V_U = new TreeMap<Double, Double> (); 
		while (scanner.hasNextLine()) {
			Double u = scanner.nextDouble();
			Double v = scanner.nextDouble();
			V_U.put(u, v);
		}
		StatTest test = new X2Test(0.05, V_U);
		if (test.isH0())
			System.out.println("H0");
		else 
			System.out.println("H1");
		
	}
	
	public void doTestCoeffDifferences() throws FileNotFoundException {
		int n = 1000;
		int m = 5000;
		Double b = 2.0;
		Double [] aSet = {0.0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5};
		List<Double> B1 = new ArrayList<Double>();
		List<Double> B2 = new ArrayList<Double>();
		List<Double> B3 = new ArrayList<Double>();
		List<Double> B4 = new ArrayList<Double>();
		
		ProbDistribution distX = new ExpDistribution(1.0);
//		ProbDistribution distX = new UniformDistribution(1.0, 5.6);
		ProbDistribution distEps = new NormalDistribution(0.0,0.1);
//		ProbDistribution distEps = new LaplasDistribution(Math.sqrt(20.0),0.0);
		//		ProbDistribution distEps = new LaplasDistribution(4.5, 0.0);

//		PrintWriter out = new PrintWriter(new FileOutputStream("TestCoeffDifferences.csv", true));
		//out.println("n,a,b1,b2,b3,b4");
		
		System.out.println("n  a  b1  b2  b3  b4");
		for (Double a : aSet) {
			B1.clear();
			B2.clear();
			B3.clear();
			B4.clear();
			for (int i = 0; i < m; i++) {
				StructuralModel model = new StructuralModel(n, distX, new NormalDistribution(0.0,a/(1-a)), 
						distEps, 0.0, b);
				List<Double> U = model.getU();
				List<Double> V = model.getV();
				B1.add(new LeastSquareMethod().estimate(V, U));
				B2.add(new WLeastSquareMethod().estimate(V, U));
				B3.add(new LeastAbsMethodIterMin(0.0001).estimate(V, U));
				B4.add(new WLeastAbsMethodIterMin(0.0001).estimate(V, U));
			}
			System.out.printf("%d,%.4f,%.4f,%.4f\n", n, a, 
					Math.abs(MathCommon.getMean(B1)-MathCommon.getMean(B2))/
					Math.sqrt(MathCommon.getVar(B2)-MathCommon.getVar(B1)),
					Math.abs(MathCommon.getMean(B3)-MathCommon.getMean(B4))/
					Math.sqrt(MathCommon.getVar(B4)-MathCommon.getVar(B3)));
		}

			
	}
	
	
	
	
	
	public static void main (String[] ch) throws FileNotFoundException {
		ErrorsInVariablesTestMain main = new ErrorsInVariablesTestMain();
		main.doWork();
//		main.doTestCoeffDifferences();
	}
	
}
